﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.DataVisualization.Charting;

namespace Echart
{
    internal class EchartHelper
    {
        static List<Color> listColors = new List<Color>();//颜色
        const BindingFlags InstanceBindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;//类属性范围
        /// <summary>
        /// 设置标题
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        public static void SetEcharTitle(Chart chart, string title)
        {
            System.Windows.Forms.DataVisualization.Charting.Title title1 = new Title();
            title1.Alignment = System.Drawing.ContentAlignment.TopCenter;
            title1.Font = new System.Drawing.Font("Trebuchet MS", 14.25F, System.Drawing.FontStyle.Bold);
            title1.ForeColor = System.Drawing.Color.FromArgb(((int)((byte)(26))), ((int)((byte)(59))), ((int)((byte)(105))));
            title1.Name = "title1";
            title1.Position.Auto = false;
            title1.Position.Height = 8.738057F;
            title1.Position.Width = 80F;
            title1.Position.X = 10F;
            title1.Position.Y = 4F;
            title1.ShadowColor = System.Drawing.Color.FromArgb(((int)((byte)(32))), ((int)((byte)(0))), ((int)((byte)(0))), ((int)((byte)(0))));
            title1.ShadowOffset = 3;
            title1.Text = title;
            chart.Titles.Add(title1);
        }
        /// <summary>
        /// 设置样式
        /// </summary>
        /// <param name="chart"></param>
        public static void SetEchartStyle(Chart chart)
        {
            chart.BackColor = System.Drawing.Color.FromArgb(((int)((byte)(243))), ((int)((byte)(223))), ((int)((byte)(193))));
            chart.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom;
            chart.BorderlineColor = System.Drawing.Color.FromArgb(((int)((byte)(181))), ((int)((byte)(64))), ((int)((byte)(1))));
            chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
            chart.BorderlineWidth = 2;
            chart.BorderSkin.SkinStyle = System.Windows.Forms.DataVisualization.Charting.BorderSkinStyle.Emboss;
            chart.Name = "chart1";
            chart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.Pastel;
        }
        /// <summary>
        /// 数据区域设置（ChartArea）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chart"></param>
        /// <param name="dataLists"></param>
        /// <param name="IsEnable3D"></param>
        public static void SetChartArea<T>(Chart chart, List<T> dataLists, bool IsEnable3D = false)
        {
            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new ChartArea();

            chartArea1.Area3DStyle.Enable3D = IsEnable3D;
            chartArea1.Area3DStyle.Inclination = 10;
            chartArea1.Area3DStyle.Rotation = 10;
            chartArea1.Area3DStyle.IsClustered = true;
            chartArea1.Area3DStyle.IsRightAngleAxes = false;
            chartArea1.Area3DStyle.Perspective = 10;
            chartArea1.Area3DStyle.PointGapDepth = 20;
            chartArea1.Area3DStyle.WallWidth = 0;

            //横坐标设置
            double from = 0.5, to = 1.5;//坐标初始位置
            foreach (T list in dataLists)
            {
                System.Windows.Forms.DataVisualization.Charting.CustomLabel customLabel1 = new CustomLabel();
                customLabel1.FromPosition = from;
                customLabel1.ToPosition = to;
                customLabel1.Text = list.GetType().GetProperty("name").GetValue(list, null).ToString();
                chartArea1.AxisX.CustomLabels.Add(customLabel1);
                //下一个位置
                from += 1;
                to += 1;
            }

            chartArea1.AxisX.Interval = 1;
            chartArea1.AxisX.IsLabelAutoFit = false;
            chartArea1.AxisX.LabelStyle.Font = new Font("Trebuchet MS", 8.25F);//x轴字体大小
            chartArea1.AxisX.LineColor = Color.FromArgb(((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))));
            chartArea1.AxisX.MajorGrid.LineColor = Color.FromArgb(((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))));
            chartArea1.AxisY.IsLabelAutoFit = false;
            chartArea1.AxisY.LabelStyle.Font = new Font("Trebuchet MS", 8.25F, FontStyle.Bold);//y轴字体大小
            chartArea1.AxisY.LineColor = Color.FromArgb(((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))));
            chartArea1.AxisY.MajorGrid.LineColor = Color.FromArgb(((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))));
            chartArea1.BackColor = Color.OldLace;
            chartArea1.BackSecondaryColor = Color.White;
            chartArea1.BorderColor = Color.FromArgb(((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))), ((int)((byte)(64))));
            chartArea1.Name = "Default";
            chartArea1.Position.Auto = false;
            chartArea1.Position.Height = 75F;
            chartArea1.Position.Width = 95F;
            chartArea1.Position.Y = 8F;
            chartArea1.ShadowColor = Color.Transparent;
            chart.ChartAreas.Add(chartArea1);
        }
        /// <summary>
        /// 颜色设置
        /// </summary>
        /// <param name="colors"></param>
        public static void SetColor(List<Color> colors)
        {
            listColors = colors;
        }
        /// <summary>
        /// 数据显示区域设置（Lengend）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chart"></param>
        /// <param name="dataLists"></param>
        public static void SetLengend<T>(Chart chart, List<T> dataLists)
        {
            System.Windows.Forms.DataVisualization.Charting.Legend lengend1 = new Legend();
            lengend1.BackColor = Color.Transparent;
            lengend1.Enabled = false;
            lengend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
            lengend1.Name = "Default";
            lengend1.Position.Auto = false;
            lengend1.Position.Height = 5F;
            lengend1.Position.Width = 40F;
            lengend1.Position.X = 5F;
            lengend1.Position.Y = 85F;
            chart.Legends.Add(lengend1);

            //设置名称
            System.Windows.Forms.DataVisualization.Charting.Legend lengend3 = new Legend();
            int colorIndex = 0;
            //PropertyInfo[] attributes = dataLists[0].GetType().GetProperties(InstanceBindFlags);//可以访问类的公共属性
            PropertyInfo[] attributes = dataLists[0].GetType().GetProperties();//只能访问类的公共属性（piblic),且属性有get和set方法
            foreach (PropertyInfo attribute in attributes)
            {
                Object value = attribute.GetValue(dataLists[0], null);
                string attributeName = attribute.Name;

                if (value.GetType() == typeof(string))
                    continue;

                System.Windows.Forms.DataVisualization.Charting.LegendItem legendItem1 = new LegendItem();
                lengend3.BackColor = Color.Transparent;
                legendItem1.Color = listColors[colorIndex];
                legendItem1.Name = attributeName;
                colorIndex++;
                lengend3.CustomItems.Add(legendItem1);
            }

            lengend3.Font = new Font("Trebuchet MS", 8.25F, FontStyle.Bold);
            lengend3.IsTextAutoFit = false;
            lengend3.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
            lengend3.Name = "Lengend3";
            lengend3.Position.Auto = false;
            lengend3.Position.Height = 12F;
            lengend3.Position.Width = 90F;
            lengend3.Position.X = 5F;
            lengend3.Position.Y = 85F;
            chart.Legends.Add(lengend3);
        }

        /// <summary>
        /// 数据注入(Series)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public static void SetSeries<T>(Chart chart, List<T> dataLists, SeriesChartType chartType)
        {
            PropertyInfo[] attributes = dataLists[0].GetType().GetProperties();
            int colorIndex = 0;
            foreach (PropertyInfo attribute in attributes)
            {
                Object value = attribute.GetValue(dataLists[0], null);
                string attributeName = attribute.Name;
                if (value.GetType() == typeof(string))
                    continue;

                System.Windows.Forms.DataVisualization.Charting.Series series1 = new Series();
                series1.BorderColor = Color.FromArgb(((int)((byte)(180))), ((int)((byte)(26))), ((int)((byte)(59))), ((int)((byte)(105))));
                series1.ChartArea = "Default";
                series1.LabelAngle = -90;
                series1.MarkerSize = 10;
                series1.ChartType = chartType;//设置图表类型（柱状，曲线等）
                series1.Color = listColors[colorIndex];
                series1.CustomProperties = "DrawingStyle=Cylinder";
                series1.Legend = "Default";
                series1.BorderWidth = 2;

                //series1.MarkerStyle = MarkerStyle.Circle;

                double x = 1, y = 0;
                foreach (T dataList in dataLists)
                {
                    y = Convert.ToDouble(dataList.GetType().GetProperty(attributeName).GetValue(dataList, null));
                    System.Windows.Forms.DataVisualization.Charting.DataPoint dataPoint1 = new DataPoint(x, y);
                    series1.Points.Add(dataPoint1);
                    x++;
                }

                series1.ShadowColor = Color.Transparent;
                series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
                series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
                chart.Series.Add(series1);
                colorIndex++;
            }
            //柱状图上显示数据
            foreach (Series series in chart.Series)
            {
                series.IsValueShownAsLabel = true;
            }
        }
        /// <summary>
        /// 初始化图表（开启3D）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chart"></param>
        /// <param name="dataLists"></param>
        /// <param name="colors"></param>
        /// <param name="chartType"></param>
        /// <param name="title"></param>
        public static void InitEchart3D<T>(Chart chart, List<T> dataLists, List<Color> colors, SeriesChartType chartType = SeriesChartType.Spline, string title = "")
        {
            SetEcharTitle(chart, title);
            SetEchartStyle(chart);
            SetChartArea(chart, dataLists, true);//开启3D效果
            SetColor(colors);
            SetLengend(chart, dataLists);
            SetSeries(chart, dataLists, chartType);


        }
        /// <summary>
        /// 初始化图表（不开启3D）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chart"></param>
        /// <param name="dataLists"></param>
        /// <param name="colors"></param>
        /// <param name="chartType"></param>
        /// <param name="title"></param>
        public static void InitEchart<T>(Chart chart, List<T> dataLists, List<Color> colors, SeriesChartType chartType = SeriesChartType.Spline, string title = "")
        {
            SetEcharTitle(chart, title);
            SetEchartStyle(chart);
            SetChartArea(chart, dataLists);//开启3D效果
            SetColor(colors);
            SetLengend(chart, dataLists);
            SetSeries(chart, dataLists, chartType);
        }

        #region  动态曲线图
        /// <summary>
        /// x轴最大数量
        /// </summary>
        static int xValue = 6;
        static int pointCount = 0;//point个数
        //增加队列
        static List<Queue<double>> pointXs = new List<Queue<double>>();
        static List<Queue<double>> pointYs = new List<Queue<double>>();
        /// <summary>
        /// 动态曲线图初始化
        /// </summary>
        /// <param name="chart"></param>
        public static void InitDynamicEchart(Chart chart, int seriesCount)
        {

            //System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new ChartArea();
            //chartArea1.Position.Auto = false;
            //chartArea1.Name = "Default";
            //chartArea1.Position.Width = 95F;
            //chartArea1.Position.Height = 85F;
            //chart.ChartAreas.Add(chartArea1);

            System.Windows.Forms.DataVisualization.Charting.Legend lengend1 = new Legend();
            lengend1.Name = "Default";
            lengend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Bottom;
            lengend1.Alignment = StringAlignment.Center;
            chart.Legends.Add(lengend1);


            for (int i = 0; i < seriesCount; i++)
            {
                Queue<double> pointX = new Queue<double>();
                Queue<double> pointY = new Queue<double>();
                pointXs.Add(pointX);
                pointYs.Add(pointY);

                System.Windows.Forms.DataVisualization.Charting.Series series1 = new Series();
                //清空数据
                series1.Points.Clear();

                //series绘制
                series1.LegendText = "瞬时速度" + (i + 1);
                series1.ChartType = SeriesChartType.Spline;
                series1.XValueType = ChartValueType.Auto;
                series1.IsValueShownAsLabel = true;
                series1.BorderWidth = 2;
                series1.MarkerStyle = MarkerStyle.Circle;
                series1.MarkerSize = 5;
                series1.Color = Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(224)))), ((int)(((byte)(64)))), ((int)(((byte)(10)))));
                series1.Legend = "Default";
                chart.Series.Add(series1);
                chart.Series[i]["LabelStyle"] = "right";//label位置
            }

            //x轴设置
            chart.ChartAreas[0].AxisX.TitleAlignment = StringAlignment.Near;
            chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            chart.ChartAreas[0].AxisX.IntervalType = DateTimeIntervalType.Auto;
            chart.ChartAreas[0].AxisX.IsMarginVisible = false;//设置x轴起始位从y轴开始
            //y轴设置
            chart.ChartAreas[0].AxisY.TitleAlignment = StringAlignment.Center;
            chart.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
            chart.ChartAreas[0].AxisY.Minimum = 0;
            chart.ChartAreas[0].AxisY.Maximum = 90;
            chart.ChartAreas[0].AxisY.Interval = 20;

        }
        /// <summary>
        /// 图表根据数据刷新
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="y"></param>
        /// <param name="x"></param>
        public static void timerTick(Chart chart, List<PointXY> PointXYs)
        {
            //更新实时数据最近的10个
            UpdateChartData(PointXYs);

            //重新绘制
            int seriesIndex = 0;
            foreach (PointXY pointXY in PointXYs)
            {
                chart.Series[seriesIndex].Points.Clear();
                chart.Series[seriesIndex].Points.DataBindXY(pointXs[seriesIndex], pointYs[seriesIndex]);
                seriesIndex++;
            }


        }
        /// <summary>
        /// 更新数据
        /// </summary>
        public static void UpdateChartData(List<PointXY> pointXYs)
        {
            int seriesIndex = 0;
            foreach (PointXY pointXY in pointXYs)
            {
                pointXs[seriesIndex].Enqueue(pointCount);
                pointYs[seriesIndex].Enqueue(pointXY.y);
                if (pointXs[seriesIndex].Count > xValue)
                {
                    pointXs[seriesIndex].Dequeue();
                    pointYs[seriesIndex].Dequeue();
                }
                seriesIndex++;
            }
            pointCount++;

        }
        #endregion
    }
}
